
#include "Aggregator.h"
#include <utility>

using namespace npIterator;
using namespace std;


Aggregator::Aggregator() // : BaseClass()
{
    this->occupied = 0;
    this->stuffLen = Aggregator::initCapacity;
    this->stuffs = unique_ptr<Stuff[]>(new Stuff[Aggregator::initCapacity]);
    this->iter.reset();
}

Aggregator::~Aggregator()
{
    
}

Aggregator::Aggregator(const Aggregator& cpy) // : BaseClass(cpy)
{
    this->occupied = cpy.occupied;
    this->stuffLen = cpy.stuffLen;
    this->stuffs = unique_ptr<Stuff[]>(new Stuff[cpy.stuffLen]);
    for (size_t i = 0; i < cpy.occupied; i++)
    {
        this->stuffs[i] = cpy.stuffs[i];
    }

    //this->iter本身处于初始状态，不调用reset()也可
    this->iter.reset();
}

Aggregator& Aggregator::operator=(const Aggregator& asn)
{
    if (this == &asn)
    {
        return *this;
    }
    else
    {
        // BaseClass::operator=(asn);
        
        //To do
        this->occupied = asn.occupied;
        this->stuffLen = asn.stuffLen;
        this->stuffs = unique_ptr<Stuff[]>(new Stuff[asn.stuffLen]);
        for (size_t i = 0; i < asn.occupied; i++)
        {
            this->stuffs[i] = asn.stuffs[i];
        }
        this->iter.reset();
        
        return *this;
    }
}

Aggregator::Aggregator(Aggregator&& mov) noexcept // : BaseClass(move(mov))
{
    this->occupied = mov.occupied;
    this->stuffLen = mov.stuffLen;
    this->stuffs = move(mov.stuffs);
    this->iter.reset();
}

Aggregator& Aggregator::operator=(Aggregator&& mva) noexcept
{
    if (this == &mva)
    {
        return *this;
    }
    else
    {
        // BaseClass::operator=(move(mva));
        
        //To do
        this->occupied = mva.occupied;
        this->stuffLen = mva.stuffLen;
        this->stuffs = move(mva.stuffs);
        this->iter.reset();
        
        return *this;
    }
}

Aggregator* Aggregator::clone() const
{
    // return nullptr;
    return new Aggregator(*this);
}

Aggregator* Aggregator::steal(void* sft)
{
    Aggregator* shf = static_cast<Aggregator*>(sft);
    if (this == shf)
    {
        return this;
    }
    else
    {
        if (!shf)
        {
            //new an instance if not abstract.
            shf = new Aggregator();
        }
        
        // BaseClass::steal(shf);
        
        //To do
        shf->occupied = this->occupied;
        shf->stuffLen = this->stuffLen;
        shf->stuffs = move(this->stuffs);
        shf->iter.reset();
        
        return shf;
    }
}

//other constructors

//public methods
void Aggregator::push(const Stuff& stuff) throw(ErrorEnum)
{
    if (this->occupied == this->stuffLen)
    {
        size_t tmpLen = this->stuffLen * Aggregator::increaseFactor;
        unique_ptr<Stuff[]> tmp(new Stuff[tmpLen]);
        for (size_t i = 0; i < this->occupied; i++)
        {
            tmp[i] = move(this->stuffs[i]);
        }
        
        tmp[this->occupied] = stuff;

        this->occupied += 1;
        this->stuffLen = tmpLen;
        this->stuffs = move(tmp);
        this->iter.reset();
    }
    else if (this->occupied < this->stuffLen)
    {
        this->stuffs[this->occupied] = stuff;
        this->occupied += 1;
    }
    else if (this->occupied > this->stuffLen)
    {
        throw ErrorEnum::WierdError;
    }
}

void Aggregator::pop(size_t indx) throw()
{
    if (indx >= this->occupied
    || indx < 0)
    {
        return;
    }
    
    for (size_t i = indx + 1; i < this->occupied; i++)
    {
        this->stuffs[i - 1] = move(this->stuffs[i]);
    }
    
    this->occupied -= 1;
    // this->stuffLen 
    // this->stuffs
    this->iter.reset();
}

Stuff& Aggregator::getByIndex(size_t indx) const throw(ErrorEnum)
{
    if (indx < 0
    || indx >= this->occupied)
    {
        throw ErrorEnum::IndexOutOfRange;
    }
    
    return this->stuffs[indx];
}

//protected methods

//private methods

//static part
int Aggregator::initCapacity = 10;
float Aggregator::increaseFactor = 1.5f;

//others
